#pragma once
#include <QDebug>
#include <QString>
#include <QToolBar>
#include <QMenu>
#include <QAction>          /// Plugins define actions for toolbar buttons and such
#include <QTreeWidgetItem>  /// Plugins define items for layer tree menu
#include <QFileInfo>        /// To automatically determine basename
#include <QObject>          /// Base Qt
#include "ModelRenderer.h"

#include "qt3d/math3d/qbox3d.h"
#include "dynamic_common_global.h"

class DecoratePlugin;

/// Interface of the basic characteristics that every model needs to have
class DYNAMIC_COMMON_EXPORT Model : public QObject{
    Q_OBJECT

    /// @{ constructor
    public:
        /// @brief Basic constructor
        Model(QString path, QString name=QString());
    private:    
        /// @brief Constructor helper (not required in new C++11)
        void init(){
            this->_defaultRenderer = new ModelRenderer();
            this->_renderer = NULL;
            this->path = "";
            this->name = "";
            this->color = Qt::white;
            this->isVisible = true;
            this->isModified = false;
        }
    /// @}
    
    /// @{ @name Rendering System
    private:
        /// When none is specified, this is the one that gets used
        ModelRenderer* _defaultRenderer;
        /// Never touch it, use renderer()
        ModelRenderer* _renderer;
    public:
        /// The decorations applied to the model rendering
        QList<DecoratePlugin*> decorators;
        /// Retrieves the currently loaded renderer (possibly the default)
        /// This method ALWAYS returns a valid renderer
        ModelRenderer* renderer();
        /// Sets the active renderer
        void setRenderer(ModelRenderer* renderer){ this->_renderer=renderer; }
    /// @}
           
public:
    bool isVisible;       /// is the current model visible?
    bool isModified;      /// has the current model been modified (and not saved)? @todo make private and setter/getter to signal
    QString name;         /// name of the model (to be used in layer pane)
    QString path;         /// full path of the file associated to the model 
    QColor color;         /// Basic color (handy to see bboxes for example)
    QMatrix4x4 transform; /// Per-model transformation (i.e. alignment matrix in a scan)
    
    
    
        
    /// @{ Basic geometry, needed for rendering
    public:
        virtual void updateBoundingBox() = 0;
        const QBox3D& getBoundingBox(){ return bbox; }
    protected: 
        QBox3D bbox;          /// Per-model bounding box (before transform is applied)
    /// @}
    
public:
    /// A class that describes this class of models in the layer editor. The 
    /// default implementation doesn't specify anything, meaning the layerDialog
    /// will create something very basic. Rather than overriding this method you 
    /// should consider using its default implementation and override "decorateLayersWidgedItem"
    virtual QTreeWidgetItem* getLayersWidgetItem(){ return NULL; }
    
    /// This takes the layer item of getLayersWidgetItem() and adds a bunch 
    /// of decorations on top of it. It is easier to customize this entry
    /// in your custom made model
    /// The default implementation just shows the full path as first entry
    virtual void decorateLayersWidgedItem(QTreeWidgetItem* parent);
    
    /// A model is entitled to fill its own menus and toolbars (auto-updated on selection)
    /// By default it fills in the rendering modes
    virtual void setup(QMenu* modelMenu, QToolBar* modelToolbar);
};

Q_DECLARE_INTERFACE(Model, "starlab.interface.Model/1.0")
